package vip.xiaonuo.bi.core.datasource.factory;

import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import lombok.extern.slf4j.Slf4j;
import vip.xiaonuo.bi.core.datasource.common.AbstractDataSourceConfig;
import vip.xiaonuo.bi.core.datasource.common.RdbmsDataSourceConfig;
import vip.xiaonuo.common.exception.CommonException;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 常用数据库工厂 用于处理 获取连接与关闭数据 处理连接等
 * @author 顾育司
 * @date  2023/12/15 12:09
 */
@Slf4j
public abstract class AbstractConectionFactory {

    private final  static Map<String,HikariDataSource> DATA_SOURCE_MAP = new ConcurrentHashMap<>();

    protected abstract String getDriverClass();
    /**
     * 测试数据库是否连接上
     * @param config 数据连接配置
     * @return
     */
    public Boolean testConnection(AbstractDataSourceConfig config) throws Exception{
        Connection conn = null;
        Statement statement = null;
        try {
            conn = getConnection(config);
            System.out.println(conn);
            if (ObjectUtils.isNotEmpty(conn)) {
                conn.isValid(5);
            }
            return true;
        } catch (Exception e) {
            throw new CommonException(e.getMessage(), e);
        } finally {
            close(conn, statement,null);
        }
    }


    /**
     * 通过数据库连接池来连接
     * @param config
     * @return
     * @throws Exception
     */
    public HikariDataSource getHikariDataSource(AbstractDataSourceConfig config) throws Exception {

        RdbmsDataSourceConfig rdbmsDataSourceConfig = (RdbmsDataSourceConfig) config;

         // 定义配置项
        HikariConfig hikariConfig = new HikariConfig();


        // 基础配置
        hikariConfig.setDriverClassName(getDriverClass()); // 获取子类对应类型的驱动类
        hikariConfig.setJdbcUrl(rdbmsDataSourceConfig.getUrl());
        hikariConfig.setUsername(rdbmsDataSourceConfig.getUsername());
        hikariConfig.setPassword(rdbmsDataSourceConfig.getPassword());

        // 连接池配置
        if (config.getExtendParamConfig()!=null&&config.getExtendParamConfig().getPoolConfig()!=null) {
            hikariConfig.setConnectionTimeout(rdbmsDataSourceConfig.getExtendParamConfig().getPoolConfig().getConnectionTimeout());
            hikariConfig.setIdleTimeout(rdbmsDataSourceConfig.getExtendParamConfig().getPoolConfig().getIdleTimeout());
            hikariConfig.setMaxLifetime(rdbmsDataSourceConfig.getExtendParamConfig().getPoolConfig().getMaxLifetime());
            hikariConfig.setMaximumPoolSize(rdbmsDataSourceConfig.getExtendParamConfig().getPoolConfig().getMaximumPoolSize());
            hikariConfig.setMinimumIdle(rdbmsDataSourceConfig.getExtendParamConfig().getPoolConfig().getMinimumIdle());
            hikariConfig.setReadOnly(rdbmsDataSourceConfig.getExtendParamConfig().getPoolConfig().getReadOnly());
        }
        // todo 自定义参数处理暂时不做处理 jdbc连接后面用&xxx=xx即可配置

        return new HikariDataSource(hikariConfig);
    }


    /**
     * 通过数据库连接
     * @param config
     * @return
     */
    public Connection getConnection(AbstractDataSourceConfig config) throws Exception{
        HikariDataSource hikariDataSource = DATA_SOURCE_MAP.get(config.getSourceId());
        if (hikariDataSource==null){
            hikariDataSource = getHikariDataSource(config);
            DATA_SOURCE_MAP.put(config.getSourceId(),hikariDataSource);
        }
        // 2数据库连接池连接
        return hikariDataSource.getConnection();
    }




    /**
     * 关闭数据库相关连接
     * @param conn
     * @param statement
     */
    public void  close(Connection conn, Statement statement, ResultSet resultSet){
        try {
            // 关闭statement对象
            if (statement != null) {
                statement.close();
            }
            // 关闭conn对象
            if (conn != null) {
                conn.close();
            }

            // 关闭conn对象
            if (resultSet != null) {
                resultSet.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }


}
